/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bef.api.be;

import com.inspur.edp.bef.api.lcp.BefTempTableContext;
import com.inspur.edp.bef.api.parameter.clone.CloneParameter;
import com.inspur.edp.bef.api.parameter.retrieve.RespectiveRetrieveResult;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveChildResult;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveResult;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.action.EditResult;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.variable.api.data.IVariableData;
import com.inspur.edp.commonmodel.api.ICMManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * BE内置自定义动作接口
 * 本类被{@link com.inspur.edp.bef.api.lcp.IStandardLcp}和{@link IBEManager}继承，因此本类上提供的方法可以同时被外部调用或在BE自定义动作中调用。
 */
public interface IBEService extends ICMManager {

  //region 新增
  /**
   * 新增主表业务实体数据，实体数据中带有默认值。关于默认值的说明可以参考{@link #retrieveDefault(Map)}。
   * <p>新增的数据的ID是自动生成的，禁止修改其ID。如需新增指定ID的数据，请使用{@link #retrieveDefault(String)}
   * 或{@link #retrieveDefault(List)}.
   * @return 实体数据
   */
  IEntityData retrieveDefault();

  /** 新增ID为特定值的主表业务实体数据，实体数据中带有默认值 */
  IEntityData retrieveDefault(String dataID);


  IEntityData retrieveDefault(String dataID,java.util.Map<String, Object> defaultValues);

  /**
   * 复制指定数据
   * @param cloneDataID 被复制数据id
   * @return
   */
  IEntityData clone(String cloneDataID, CloneParameter cloneParameter);

  /**
   * 复制指定数据
   * @param cloneDataID 被复制数据id
   * @param dataID 新数据id
   * @return
   */
  IEntityData clone(String cloneDataID, String dataID, CloneParameter cloneParameter);

  /**
   * 批量新增多条ID为特定值的主表业务实体数据，新增的数据行数与{@code dataIDs}参数所代表的列表长度一致。
   *
   * @param dataIDs ID列表，由于数据主键不允许重复不允许为{@code null}，所以此列表中的值不允许重复，不允许包含{@code null}
   * */
  Map<String, IEntityData> retrieveDefault(List<String> dataIDs);

  /**
   * 新增主表业务实体数据，实体数据中带有传入的默认值。默认值的来源有：
   * <ul><li>字段类型固有默认值（通常为{@code null}，如果在WebIde上将字段的“默认为空”属性设置为false，则使用字段的非{@code null}默认值，如Integer或BigDecimal为0，String为“”等）；
   * <li>通过WebIde设计器中给字段设置的默认值；
   * <li>通过{@code defaultValues}参数传入的默认值；
   * <li>字段上设置的新增时生成的编号规则；
   * <li>通过新增后联动计算设置的默认值；</ul>
   * 以上默认值规则按顺序从上至下进行，上面的默认值与下面的默认值如有重复，下面将覆盖上面。
   * <p>新增的数据的ID是自动生成的，禁止修改其ID。如需新增指定ID的数据，请使用{@link #retrieveDefault(String)}
   * 或{@link #retrieveDefault(List)}.
   *
   * @param defaultValues 传入的默认值，默认值中不能包含主键字段
   * @return 新增的主表实体数据
   */
  IEntityData retrieveDefault(java.util.Map<String, Object> defaultValues);

  /**
   * 新增业务实体的从(从)表数据。默认值规则与{@link #retrieveDefault(Map)}一致。
   * 新增从（从）表数据时，必须提供一个上级数据的Id，且这个Id所代表的上级数据必须存在。上级数据的Id将被赋值到从（从）表数据的ParentId字段上。
   * 如果上级数据不存在，或{@code nodeCodes}参数构造不正确，将会引发编号为{@code GSP_ADP_BEF_2004}的
   * {@link com.inspur.edp.bef.api.exceptions.BefException}异常，异常提示多为“ID为xxx的数据不存在”。
   * <p>新增的数据的ID是自动生成的，禁止修改其ID。如需新增指定ID的数据，请使用{@link #retrieveDefaultChild(List, List, String)}
   * 或{@link #retrieveDefaultChild(List, List, List)}。
   * <ul><li>1. 新增从表数据时，{@code nodeCodes}中要包含从表实体编号，{@code hierachyIds}中要包含主表数据的唯一标识；
   * <li>2.该方法不只支持新增从表数据，同样的也可以新增从从表数据。新增从从表数据时，{@code nodeCodes}中要包含从从表所属的从表实体编号，
   * 以及从从表的实体编号，{@code hierachyIds}中要包括对应主表数据的唯一标识、子表数据的唯一标识。</ul>
   * <p>下面通过一个例子说明{@code nodeCodes}和{@code hierachyIds}两个参数如何构造。
   * <p>假设有一个业务实体，其主表为A，A下有从表B，B下有从从表C。
   * <p>如果需要新增一条B（从表）实体数据，此时两个参数分别应为：
   * <ul><li>{@code nodeCodes}：{@code java.util.Arrays.asList("B");}
   * <li>{@code hierachyIds}：{@code java.util.Arrays.asList("A实体数据Id");}</ul>
   * <p>如果需要新增一条C（从从表）实体数据，此时两个参数分别应为：
   * <ul><li>{@code nodeCodes}：{@code java.util.Arrays.asList("B", "C");}
   * <li>{@code hierachyIds}：{@code java.util.Arrays.asList("A实体数据Id", "B实体数据Id");}</ul>
   * 此外，如果是生成型的BE元数据，在WebIde中点击生成代码菜单后，在生成的I{BE编号}Service接口中会针对每个从（从）表
   * 生成对应的新增方法。上述例子中，将在IAService接口中自动生成如下几个方法（实现也是自动生成的）：
   * <ul><li>retrieveDefaultB(String aId);
   * <li>retrieveDefaultB(String aId, String bId);</ul>
   * 可以看到，使用这些生成的方法，参数更加清晰、使用不易犯错，因此对于生成型BE推荐使用自动生成的新增从（从）表方法。
   *
   * @param nodeCodes 要新增数据的从(从)表的实体编号
   * @param hierachyIds 新增从(从)表数据的所属实体数据的唯一标识
   * @return 新增的从(从)表实体数据
   */
  IEntityData retrieveDefaultChild(
      java.util.List<String> nodeCodes, java.util.List<String> hierachyIds);

  /**
   * 新增业务实体的从(从)表数据。
   * 用法与{@link #retrieveDefaultChild(List, List)}基本一致，唯一的区别是{@link #retrieveDefaultChild(List, List)}
   * 新增的数据的ID是自动生成的且禁止修改。使用此方法可以通过第三个参数指定ID。
   *
   * @param nodeCodes 要新增数据的从(从)表的实体编号
   * @param hierachyIdList 新增从(从)表数据的所属实体数据的唯一标识
   * @param dataID 新增从(从)表数据的所属实体数据的唯一标识
   * @return 新增的从(从)表实体数据
   * 
   * @see #retrieveDefaultChild(List, List)
   */
  IEntityData retrieveDefaultChild(
      java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, String dataID);

  /**
   * 批量新增业务实体的从(从)表数据。除了第三个参数外，其他用法与{@link #retrieveDefaultChild(List, List)}一致。
   *
   * @param nodeCodes
   * @param hierachyIdList
   * @param dataIDs 指定批量新增的实体数据的ID
   * @return 新增的从(从)表实体数据，Map的key为实体数据ID
   * 
   * @see #retrieveDefaultChild(List, List)
   */
  Map<String, IEntityData> retrieveDefaultChild(java.util.List<String> nodeCodes,
      java.util.List<String> hierachyIdList, List<String> dataIDs);

  /**
   * 使用指定的默认值新增业务实体的从(从)表数据。
   * 除了第三个参数外，其他用法与{@link #retrieveDefaultChild(List, List)}一致。
   * <p>新增的数据的ID是自动生成的，禁止修改其ID。如需新增指定ID的数据，请使用{@link #retrieveDefaultChild(List, List, String)}
   * 或{@link #retrieveDefaultChild(List, List, List)}。
   * <p>注意：第三个参数，即默认值列表中不能包含主键，如包含将会引发异常。
   *
   * @param nodeCodes 要新增数据的从(从)表的实体编号
   * @param hierachyIdList 新增从(从)表数据的所属实体数据的唯一标识
   * @param defaultValues 从(从)表新增数据使用的默认值, 注意：其中不能包含主键
   * @return 新增的从(从)表实体数据
   *
   * @see #retrieveDefaultChild(List, List)
   */
  IEntityData retrieveDefaultChild(
      java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, java.util.Map<String, Object> defaultValues);
  //endregion


  //region 无session方法
  /**
   * 创建默认数据（不放到缓存、字段初始值使用字段类型固有默认值）
   * 使用此方法创建的数据默认不会被保存到持久化。
   *
   * @return 默认数据
   */
  IEntityData createObjectData();

  /** 序列化实体数据 */
  @Override
  String serializeData(IEntityData data);

  /** 反序列化实体数据 */
  IEntityData deSerializeData(String data);

  //endregion


  //region 检索
  /**
   * 使用不加锁的方式检索指定ID的实体数据。
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如需对检索行为进行更精细化的控制，请使用{@link #retrieve(String, RetrieveParam)}
   * <p>如返回结果{@link RespectiveRetrieveResult#getData()}为null，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param id 实体数据的唯一标识
   * @return 检索的返回结果，包含实体数据和加锁是否成功等。无论实体数据是否存在，此方法返回值一定不为{@code null}。
   *
   * @see #retrieve(String, RetrieveParam)
   */
  RespectiveRetrieveResult retrieve(String id);

  /**
   * 加锁并检索数据
   * <p>如果加锁失败会抛出编号GSP_ADP_BEF_2001的{@link com.inspur.edp.bef.api.exceptions.BefException}，
   * 异常信息不同场景稍有不同，中文异常信息一般为“数据已被锁定...”。
   * @param id
   * @return 检索结果
   */
  EditResult edit(String id);

  /**
   * 检索指定ID的实体数据，可指定是否加锁
   * <p>注意，如果加锁失败，此方法不会抛出异常，而是通过将返回值上的{@link RespectiveRetrieveResult#getLockFailed()}置为false代表加锁失败。
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如果希望在加锁失败后抛出异常以中止后续代码逻辑，应使用{@link #edit(String)}方法，或增加逻辑进行判断。
   * <p>在自定义动作中执行实体动作前通常需要先进行检索，如果实体动作中可能修改数据，
   * 那么推荐使用{@link #edit(String)}方法进行加锁并检索，而不是retrieve方法。
   * 因为{@code retrieve}方法默认不进行加锁这一点容易被开发人员忽略，同时也不容易通过测试发现。
   * <p>如返回结果{@link RespectiveRetrieveResult#getData()}为null，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param id 实体数据的唯一标识
   * @param retrieveParam 检索参数
   * @return 检索的返回结果，及时所检索的数据不存在，返回值也不会是null，仅{@link RespectiveRetrieveResult#getData()}会返回null
   * 
   * @see #edit(String)
   */
  RespectiveRetrieveResult retrieve(String id, RetrieveParam retrieveParam);

  /**
   * 检索一组指定ID的实体数据，默认采用加锁的方式检索
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如返回结果{@link RetrieveResult#getDatas()}中包含null值，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param idList 一组实体数据的唯一标识
   * @return 检索的返回结果
   */
  RetrieveResult retrieve(List<String> idList);

  /**
   * 检索一组指定ID的实体数据，可指定是否使用加锁方式
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如返回结果{@link RetrieveResult#getDatas()}中包含null值，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param idList 一组实体数据的唯一标识
   * @param retrieveParam 检索参数
   * @return 检索的返回结果
   */
  RetrieveResult retrieve(List<String> idList, RetrieveParam retrieveParam);

  /**
   * 检索指定ID的子表数据，可指定检索时是否加锁。
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如返回结果{@link RespectiveRetrieveResult#getData()}为null，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param nodeCodes 除根节点外从上级到下级的节点编号
   * @param hierachyIdList 除根节点外从上级到下级的数据ID
   * @param par 检索数据时的参数
   * @return 检索返回结果
   */
  RespectiveRetrieveResult retrieveChild(
      java.util.List<String> nodeCodes, java.util.List<String> hierachyIdList, RetrieveParam par);

  /**
   * 检索指定ID的子表数据，可指定检索时是否加锁。前两个参数的构造方法可以参考{@link #retrieveDefaultChild(List, List)}。
   * <p>注意，通过此方法检索得到的数据不应进行任何修改，强行修改可能导致编号为{@code Cef3001}的{@link io.iec.edp.caf.commons.exception.CAFRuntimeException}异常，如需修改请使用{@link #modify(IChangeDetail)}。
   * <p>如返回结果{@link RetrieveChildResult#getDatas()}中包含null值，说明数据已经被删除或数据不存在，请检查传入参数是否正确、数据是否在调用检索(retrieve)前曾经调过delete、当前连接到正确的数据库等。
   *
   * @param nodeCodes 除根节点外从上级到下级的节点编号
   * @param hierachyIdList 根节点从上级到下级的数据ID
   * @param par 检索数据时的参数
   * @param ids 从表或从从表数据id列表
   * @return 检索返回结果
   */
  RetrieveChildResult retrieveChild(List<String> nodeCodes, List<String> hierachyIdList,
      ArrayList<String> ids, RetrieveParam par);
  //endregion


  //region 修改
  /**
   * 将业务实体数据的变更集提交到内存。若想将变更集提交到数据库，需要在调用Modify方法之后，再调用Save方法。
   * <p>使用变更集既可以修改主表数据，也可以修改从（从）表数据。
   * <p>参数{@code changeDetail}上{@link IChangeDetail#getDataID()}代表要修改的数据的主键值。
   * <p>变更集的构造方法可以<a href="https://open.inspuronline.com/iGIX/#/document/mddoc/docs-gsp-cloud-ds%2Fdev-guide-beta%2Fspecial-subject%2FBE-related%2F%E5%8F%98%E6%9B%B4%E9%9B%86%E4%BD%BF%E7%94%A8.md">点击这里</a>查看。
   * <p>如果要修改的数据不存在或已被删除，将会引发编号为{@code GSP_ADP_BEF_2004}的异常。
   *
   * @param changeDetail 实体数据的变更集，其{@link IChangeDetail#getDataID()}代表要修改的数据的主键值。
   */
  void modify(IChangeDetail changeDetail);

  /**
   * 将符合过滤条件的数据批量进行修改。若想将变更集提交到数据库，需要在调用Modify方法之后，再调用Save方法。
   *
   * @param filter 过滤条件
   * @param changeDetail 提交的变更集
   *
   * @see #modify(IChangeDetail)
   */
  void modify(EntityFilter filter, ModifyChangeDetail changeDetail);

  /**
   * 批量提交一组业务实体数据的变更集到内存。若想将变更集提交到数据库，需要在调用Modify方法之后，再调用Save方法。
   *
   * @param changeDetails 提交的变更集集合
   *
   * @see #modify(IChangeDetail)
   */
  void modify(ArrayList<IChangeDetail> changeDetails);

  //endregion

    /**
     * 查询符合过滤条件的业务实体主表数据，不包含权限的信息
     * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
     * <p>返回结果不包含任何子表数据，也不包含未持久化的修改。
     * <p>对查询结果进行任何修改都{@code 不会}被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
     *
     * @param filter 查询的过滤条件
     * @return 返回符合查询条件的业务实体主表数据集合，不含任何子表，不带权限信息
     */
  List<IEntityData> queryWithoutAuthInfo(EntityFilter filter);

  /**
   * 查询指定节点上符合过滤条件的业务实体数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回结果不包含指定节点的下级节点数据，也不包含未持久化的修改。
   * <p>对查询结果进行任何修改都{@code 不会}被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @param nodeCode
   *        节点编号
   * @param filter
   *        查询的过滤条件
   * @return 返回符合查询条件的业务实体数据集合
   */
  List<IEntityData> queryWithoutAuthInfo(String nodeCode,EntityFilter filter);
  //region 查询
  /**
   * 查询符合过滤条件的业务实体主表数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回结果不包含任何子表数据，也不包含未持久化的修改。
   * <p>对查询结果进行任何修改都不会被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @param filter 查询的过滤条件
   * @return 返回符合查询条件的业务实体主表数据集合，不含任何子表
   */
  List<IEntityData> query(EntityFilter filter);

  /**
   * 查询业务实体主表数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回结果不包含任何子表数据，也不包含未持久化的修改。
   * <p>数据量过大时可能导致性能问题，建议使用带过滤条件的{@link #query(EntityFilter)}方法进行查询。
   * <p>对查询结果进行任何修改都不会被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @return 业务实体主表数据集合，不含任何子表
   *
   * @see #query(EntityFilter)
   */
  List<IEntityData> query();

  /**
   * 查询指定节点上符合过滤条件的业务实体数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回结果不包含指定节点的下级节点数据，也不包含未持久化的修改。
   * <p>对查询结果进行任何修改都不会被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @param nodeCode
   *        节点编号
   * @param filter
   *        查询的过滤条件
   * @return 返回符合查询条件的业务实体数据集合
   */
  List<IEntityData> query(String nodeCode, EntityFilter filter);

  /**
   * 查询指定节点上符合过滤条件的业务实体子节点数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回的结果包含当前会话中未保存的修改。
   * <p>对查询结果进行任何修改都不会被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @param nodeCode
   *        节点编号
   * @param filter
   *        查询的过滤条件
   * @return 返回符合查询条件的业务实体数据集合
   */
  List<IEntityData> queryWithBuffer(String nodeCode, EntityFilter filter);

  /**
   * 查询符合过滤条件的业务实体主表数据。
   * <p>该方法不会对数据进行加锁（相比{@link #retrieve(String, RetrieveParam)}）。
   * <p>返回的结果包含当前会话中未保存的修改。
   * <p>对查询结果进行任何修改都不会被持久化，如需修改数据请使用{@link #modify(IChangeDetail)}。
   *
   * @param filter
   *        查询的过滤条件
   * @return 返回符合查询条件的业务实体主表数据集合
   */
  List<IEntityData> queryWithBuffer(EntityFilter filter);

  //endregion


  //region 删除
  /**
   * 将指定ID的业务实体数据的删除变更集提交到内存。若需要将该删除变更集提交到数据库，需要在调用Delete方法后，再调用Save方法。
   *
   * @param dataId 实体数据的唯一标识
   */
  void delete(String dataId);

  /**
   * 批量将指定ID的业务实体数据的删除变更集提交到内存。若需要将该删除变更集提交到数据库，需要在调用delete方法后，再调用save方法。
   *
   * @param dataId 实体数据的唯一标识的集合
   */
  void delete(java.util.List<String> dataId);

  /**
   * 删除实体数据上指定ID的从(从)表数据，将删除变更集提交到内存。
   * <p>若需要将该删除变更集提交到数据库，需要在调用DeleteChild方法后，再调用Save方法。
   * <p>1.删除从表数据时，nodeCodes包含从表实体编号，hierachyIdList包含主表数据的唯一标识，ids包含要删除的从表数据的唯一标识
   * <p>2.删除从(从)表数据时，nodeCodes包含从从表所属的从表实体编号、以及从从表的实体编号；hierachyIdList包含从从表数据所属的主表数据的唯一标识，
   * 以及从表数据的唯一标识，ids包含要删除的从从表数据的唯一标识。
   * <p>前两个参数的构造方法可以参考{@link #retrieveDefaultChild(List, List)}。
   * <p>如果是生成型的BE元数据，在WebIde中点击生成代码菜单后，在生成的I{BE编号}Service接口中会针对每个从（从）表
   * 生成对应的删除方法。参考{@link #retrieveDefaultChild(List, List)}方法说明中的例子，将在IAService接口中自动生成如下几个方法（实现也是自动生成的）：
   * <ul><li>deleteB(String aId, String bId);
   * <li>deleteC(String aId, String bId, String cId);</ul>
   * 可以看到，使用这些生成的方法，参数更加清晰、使用不易犯错，因此对于生成型BE推荐使用自动生成的删除从（从）表方法。
   *
   * @param nodeCodes 要删除数据的从(从)表的实体编号
   * @param hierachyIdList 要删除数据的从(从)表的所属实体数据的唯一标识
   * @param ids 要删除的从(从)表数据的唯一标识集合
   */
  void deleteChild(List<String> nodeCodes, List<String> hierachyIdList, List<String> ids);

  //endregion

  /**
   * 修改目标业务实体的变量
   * <p>不同业务实体的变量是隔离的
   * <p>主要注意, 扩展业务实体的变量与基础业务实体的变量也是隔离的, 如果正在使用或将来有可能使用运行时定制,
   * 如果通过SpringBeanUtils.getBean(ILcpFatory.class).createLcp("xxx")的方式创建IStandardLcp后调用此方法, "xxx"处不应写死, 而应该使用相关上下文中提供的configId.
   * 因为开发期只有基础业务实体而不知道扩展业务实体的configId, 写死之后在运行时定制场景下很可能出现修改了基础业务实体的变量而实际运行的是扩展业务实体从而获取不到修改后的变量的问题.
   *
   * @param change 变量变更集, 实例化一个{@link com.inspur.edp.cef.entity.changeset.ValueObjModifyChangeDetail}类的实例,
   *               然后调用{@link com.inspur.edp.cef.entity.changeset.ValueObjModifyChangeDetail#putItem(String, Object)}指定要修改的属性名和属性值(可指定多对)即可
   */
  void modifyVariable(IChangeDetail change);

  /**
   * 获取BE变量。
   * <p>
   * 关于变量的详细说明可以<a href="https://open.inspuronline.com/iGIX/#/document/mddoc/docs-gsp-cloud-ds%2Fdev-guide-beta%2Fspecial-subject%2FBE-related%2F%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F.md“>访问这里</a>查看。
   * @return BE变量数据
   */
  IVariableData getVariables();

  //endregion

  /**
   * 判断指定节点的指定ID数据是否被引用，nodeCode为可选参数，默认检查主节点数据。
   *
   * @param befConfig BE的config
   * @param dataId 要检查的数据ID
   * @param nodeCode 子节点编号
   * @return true数据被引用，false数据未被引用
   */
  boolean isReferred(String befConfig, String dataId, String nodeCode);

  /**
   * 判断指定节点的指定ID数据是否存在
   *
   * @param nodeCode 节点编号
   * @param dataId 要检查的数据ID
   * @return true数据存在，false数据不存在或被删除
   */
  boolean isEffective(String nodeCode, String dataId);

  boolean isDatasEffective(String nodeCode,List<String> dataIDs, RefObject<List<String>> noneEffectiveDatas);

  boolean isDatasEffective(String nodeCode, String propName, List<String> dataIDs, RefObject<List<String>> noneEffectiveDatas);

  /**
   * 执行自定义动作。
   * <p>对于生成型BE，在生成的I{BE编号}Service接口中，每个自定义动作都会生成为一个方法。
   * <p>对于生成型BE建议尽量直接调用接口方法，因为使用此方法，写错了方法名或参数无法在编译期发现问题只能在运行时才会报错，且性能也稍弱。
   * <p>对于解析型BE可以使用此方法。
   *
   * @param actionCode 动作编号
   * @param pars 动作参数
   * @return 动作返回值，如无返回值则返回null
   */
  public Object executeCustomAction(String actionCode, Object... pars);

  IEntityData retrieveDefault(IEntityData data);

  void modify(IEntityData data);
  BefTempTableContext createTempTable(List<String> nodeCodes);
  void dropTempTable(BefTempTableContext tempTableContext);
}
